package com.budwk.app.sso.exbean;

import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.budwk.starter.common.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.nutz.http.Http;
import org.nutz.http.Response;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.ioc.loader.annotation.Value;
import org.nutz.json.Json;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.Map;
import java.util.Random;

/**
 * 封装一些 sso 共用方法 
 *
 */
@IocBean
@Slf4j
public class SsoRequestUtil {

	@Value(name = "cusconfig.sso.serverUrl")
	public String server ;
	/**
	 * SSO-Server端 统一认证地址 
	 */
	public String authUrl =  "/sso/auth";
	
	/**
	 * 使用 Http 请求校验ticket 
	 */
	public boolean isHttp = true;
	
	/**
	 * SSO-Server端 ticket校验地址 
	 */
	public String checkTicketUrl =  "/sso/checkTicket";
	
	/**
	 * 打开单点注销功能 
	 */
	public boolean isSlo = true;
	
	/**
	 * 单点注销地址 
	 */
	public String sloUrl = "/sso/signout";
	
	/**
	 * 接口调用秘钥 
	 */
	public String secretkey = "nrXBswVLj5TRA6hS2wl1R02ncMYgCgmQ";

	public String appid = "devdfsj";

	/**
	 * SSO-Server端 查询userinfo地址 
	 */
	public String userinfoUrl =  "/sso/getData";
	/**
	 * 根据登录用户id查询生成票据，用户未登录时，无法获取
	 */
	public String ticketByLoginUrl =  "/sso/getTicketByLoginId";

	
	// -------------------------- 工具方法

	/**
	 * 据登录用户id查询生成票据，用户未登录时，无法获取
	 * @return
	 */
	public Result getTicketByLoginId() {
		if (!StpUtil.isLogin()) {
			return Result.error("当前用户未登录，无法获取票据");
		}
		String loginId = StpUtil.getLoginIdAsString();//账号id
		String timestamp = String.valueOf(System.currentTimeMillis());	// 时间戳
		String nonce = getRandomString(20);		// 随机字符串
		String sign = getSign(loginId,timestamp,nonce,secretkey);
		String url = server+ticketByLoginUrl+
				"?loginId=" + loginId +
				"&timestamp=" + timestamp +
				"&nonce=" + nonce +
				"&sign=" + sign +
				"&appid=devdfsj";
		log.info("请求用户票据：{}",url);
		Response response = Http.get(url,15000);
		log.info("请求票据 {}" ,response.getStatus());
		if (response.isOK()) {
			String content = response.getContent();
			log.info("获取票据结果 ： {}",content);
			SaResult result = Json.fromJson(SaResult.class,content);
			log.info("反序列化结果：{}" ,result.getData());
			if (result.getCode() == 200) {
				return Result.data(result.getData());
			}

		}
		return Result.error("获取票据失败");
	}


	/**
	 * 根据参数计算签名 
	 * @param loginId 账号id
	 * @param timestamp 当前时间戳，13位
	 * @param nonce 随机字符串 
	 * @param secretkey 账号id
	 * @return 签名 
	 */
	public String getSign(Object loginId, String timestamp, String nonce, String secretkey) {
		return md5("loginId=" + loginId + "&nonce=" + nonce + "&timestamp=" + timestamp + "&key=" + secretkey);
	}

	/**
	 * 指定元素是否为null或者空字符串
	 * @param str 指定元素 
	 * @return 是否为null或者空字符串
	 */
	public boolean isEmpty(Object str) {
		return str == null || "".equals(str);
	}
	
	/**
	 * md5加密 
	 * @param str 指定字符串
	 * @return 加密后的字符串
	 */
	public String md5(String str) {
		str = (str == null ? "" : str);
		char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
		try {
			byte[] btInput = str.getBytes();
			MessageDigest mdInst = MessageDigest.getInstance("MD5");
			mdInst.update(btInput);
			byte[] md = mdInst.digest();
			int j = md.length;
			char[] strA = new char[j * 2];
			int k = 0;
			for (byte byte0 : md) {
				strA[k++] = hexDigits[byte0 >>> 4 & 0xf];
				strA[k++] = hexDigits[byte0 & 0xf];
			}
			return new String(strA);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 生成指定长度的随机字符串
	 * 
	 * @param length 字符串的长度
	 * @return 一个随机字符串
	 */
	public String getRandomString(int length) {
		String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
		Random random = new Random();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < length; i++) {
			int number = random.nextInt(62);
			sb.append(str.charAt(number));
		}
		return sb.toString();
	}

	/**
	 * URL编码 
	 * @param url see note 
	 * @return see note 
	 */
	public String encodeUrl(String url) {
		try {
			return URLEncoder.encode(url, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			throw new RuntimeException(e);
		}
	}

	public static void main(String[] args) {
		SsoRequestUtil ssoRequestUtil = new SsoRequestUtil();
		Result ticketByLoginId = ssoRequestUtil.getTicketByLoginId();
		System.out.println(ticketByLoginId);
	}

}
